GLFLによるOpenGL入門:第5章 図形の描画
5.1 OpenGL の図形データ
図形データは頂点属性(attributeで表す)
位置、色、法線ベクトル
attributeを転送されるGPUメモリを頂点バッファという 多分これは誤植で頂点バッファなのでは?基素.icon
attributeにはいろいろ与えられる
「図形データ」の描画
描画手順
(1) glGenVertexArrays() で頂点配列オブジェクトを作成する。
構造体を登録する
(3) glGenBuffers() で頂点バッファオブジェクトを作成する。
(4) 作成した頂点バッファオブジェクトを glBindBuffer() で結合する
(5) glBufferData() で頂点バッファオブジェクトにデータ (頂点属性) を転送する
(6) 頂点バッファオブジェクトを glVertexAttribPointer() で attribute 変数に関連づける
(7) 頂点配列オブジェクトを結合して描画命令 (ドローコール) を実行する
完成したプログラムを眺めてみると、1-6は図形データObjectのコンストラクタで実装されている
code:cpp
glGenVertexArrays(1, &vao); // (1)
glBindVertexArray(vao); // (2)
glGenBuffers( // (3)
1, //作成するVBOの数
&vbo // VBOを格納する配列の先頭アドレス
);
// VBOの内容を描画に使う頂点属性として使うのでGL_ARRAY_BUFFERを指定する
glBindBuffer(GL_ARRAY_BUFFER, vbo); // (4)
// VBOのメモリを確保し、データ(ここではvertex)を転送する
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertexcount, vertex, GL_STATIC_DRAW); //(5)
// 結合されているVBOをvertex shaderのin変数(attribute変数)から参照できるようにする
// attribute変数がデータを取り出すVBOを設定する
glVertexAttribPointer( // (6)
// glBindAttribLocation で指定したattribute変数の場所
// vertex shaderのメンバpositionのindexは0に指定しているのでこっちも0にする
0,
size, GL_FLOAT, GL_FALSE, 0, 0);
(7)はShape->draw()で実行される
作成したプログラムのよくわからない点は、(2)がObjectのコンストラクタ以外の他にdraw()の直前に再度指定していること
5.2.4 頂点配列オブジェクトの作成
VBOとattribute変数の紐付け
glVertexAttribPointerでのindexをglBindAttribLocationのindexと同じにしなければいけない
まず、これらがvertex shaderとプログラムのオブジェクト(position)が紐づいている
code:point.vert
in vec4 position;
void main()
{
gl_Position = position;
}
code:cpp
glBindAttribLocation(
program,
0, // index
"position" // point.vertのattribute変数の名前(in vec4 position)
);
code:Object.h
Class Object { // VAO, VBOを定義
public:
Object(GLint size, GLsizei vertexcount, const Vertex *vertex) {
// 略
glVertexAttribPointer(
// glBindAttribLocation で指定したattribute変数の場所
// vertex shaderのメンバpositionのindexは0に指定しているのでこっちも0にする
0, // index
size, GL_FLOAT, GL_FALSE, 0, 0);
このObjectがどうつながるのかわかっていない基素.icon
頂点バッファに関する処理がどのような流れで行なわれていくのかを時系列に並べてみると、おおよそ次のような流れになります。
頂点の各情報をいったん配列に格納
WebGL のメソッドを使って VBO を生成
WebGL のメソッドを使い VBO に配列のデータを転送
頂点シェーダ内の attribute 変数と VBO を紐付ける
VBOのindex 0と、vertex shaderのin変数positionがglBindAttribLocation()でinexを指定してbindされる
glBindAttribLocation()のindexはなんのindexなんだっけ?
objectの使い方
Object::Vertex型の配列rectangleVertexを作るときの型の指定に利用
code:main.cpp
// 矩形の頂点の位置
constexpr Object::Vertex rectangleVertex[] = {
{-0.5f, -0.5f},
{0.5f, -0.5f},
{0.5f, 0.5f},
{ -0.5f, 0.5f }
};
図形の描画クラスのコンストラクタ
code:Shape.h.cpp
Shape(GLint size, GLsizei vertexcount, const Object::Vertex *vertex) :
// 初期化する
object(new Object(size, vertexcount, vertex)),
vertexcount(vertexcount) {
}
変数objectをObjectで補完している
図形を描画する時にはあらかじめVAOを結合しておく必要がある
Shapeを作成するときにObjectのコンストラクタで
ShapeをdrawするとglBindVertexArray(vao)が呼ばれる
これ呼ぶ必要あるの?基素.icon
ある。別の図形を書く前にbindしなおしておかないと他の図形の頂点情報が混じる可能性がある
vaoとvboがどう紐づいているの?陽に紐づけていないけど基素.icon
vaoをbindするとそのあとはvaoに頂点情報が登録されるようだ
バインドが完了すると、ここから先に行うすべての頂点関連処理(主に Attribute 系)を通じて VAO に頂点情報が登録されていきます。先ほど登場した自前の関数の中身で行っていたように、gl.bindBufferやgl.enableVertexAttribArray、gl.vertexAttribPointerなどを適宜呼び出しましょう。これらのメソッドが呼び出されるたびに VAO に情報がひとまとめにされて格納されていきます。
Shape->draw()でvaoをバインドし直しているのも別の図形を書く前にbindしなおしておかないと他の図形の頂点情報が混じる可能性があるということだろう
この文章は、vaoをbindした後にvboをbindするとvaoの管理下にvboがおかれるという意味
頂点配列オブジェクトを結合 (glBindVertexArray()) した後、頂点バッファオブジェクトを結合 (glBindBuffer()) することによって、頂点配列オブジェクトに頂点バッファオブジェクトが組み込まれます。
5.2.5 描画の実行
描画する図形データを保持したVAOを基本図形の種類を選んで描画する
やっと図形を出すことができた
https://gyazo.com/e84ec96622a280dfcdd2f29c2c74d445
ここまで書かないと試せないのは嫌だなぁ